/*实现两个日志缓冲区*/
#ifndef __M_BUFFER_H_
#define __M_BUFFER_H_
#include "util.hpp"
#include <vector>
#include <cassert>
namespace bitlog
{
    #define DEFAULT_SIZE (1*1024*1024)
    #define THRESHOLD_SIZE (8*1024*1024)//成倍增长的阈值
    #define INCREMENT_SIZE (1*1024*1024)//线性增长的增量
    class buffer
    {
        public:

        buffer():
        _buffer(DEFAULT_SIZE),
        _write_ptr(0),
        _read_ptr(0)
        {}
        //向缓冲区中写入数据
        void push( const char *data,size_t len)
        {
            //如果空间不够，可以采取两种方法，一种是扩容，一种是直接报错返回
            //一般再实践中是采用报错返回处理，因为没有无限的空间来给予扩容需求
            // if(len>writesize())
            // {
            //     return ;
            // }
            //扩容操作
            enlargesize(len);
           //正常一般扩容达到阈值之前成倍扩容，达到阈值之后线性增长

            //如果空间足够，那么就直接写入
            std::copy(data,data+len,&_buffer[_write_ptr]);
            //移动一下写入指针的位置
            movewrite(len);
        }
        size_t writesize()
        {
            return (_buffer.size()-_write_ptr);
        }
        //返回可读数据的起始地址
        const char* begin()
        {
            return &_buffer[_read_ptr];
        }
        //返回可读数据的长度
        size_t readsize()
        {
            //当前缓冲区并不是循环缓冲区，只会向后写
            return (_write_ptr-_read_ptr);
        }
        //对读写指针进行向后移动的策略
        void movewrite(size_t len)
        {
            assert((len+_write_ptr)<_buffer.size());
            _write_ptr+=len;
        }
        void moveread(size_t len)
        {
            assert(len<=readsize());
            _read_ptr+=len;
        }
        //对读写指针进行初始化
        void reset()
        {
            //空间是一直保留的
            _write_ptr=0;
            _read_ptr=0;
        }
        //对缓冲区实行交换操作
        void swap(buffer &mybuffer)
        {
            _buffer.swap(mybuffer._buffer);//交换两个类中的vector
            std::swap(_read_ptr,mybuffer._read_ptr);
            std::swap(_write_ptr,mybuffer._write_ptr);
        }
        //判断缓冲区是否为空
        bool empty()
        {
            return (_read_ptr==_write_ptr);
        }
        private:
        void enlargesize(size_t len)
        {
            if(len>writesize())
            {
                size_t newsize;
               if(_buffer.size()<THRESHOLD_SIZE)
               {
                newsize=_buffer.size()*2+len;
               }
               else
               {
                newsize=_buffer.size()+INCREMENT_SIZE+len;
               }
               _buffer.resize(newsize);
            }
            return;
        }
        std::vector<char> _buffer;
        size_t _read_ptr;
        size_t _write_ptr;
    };
} // namespace bitlog

#endif
